package cn.hzc.fortess.system.controller;

import cn.hzc.fortess.core.common.HttpContext;
import cn.hzc.fortess.core.common.ResponseData;
import cn.hzc.fortess.core.common.constant.Const;
import cn.hzc.fortess.core.common.exception.InvalidKaptchaException;
import cn.hzc.fortess.core.shiro.ShiroKit;
import cn.hzc.fortess.core.shiro.ShiroUser;
import cn.hzc.fortess.core.util.H5ToolUtil;
import cn.hzc.fortess.system.service.JwtTokenService;
import cn.hzc.fortess.system.entity.Project;
import cn.hzc.fortess.system.service.ProjectService;
import cn.hzc.fortess.system.service.SettingService;
import com.google.code.kaptcha.Constants;
import cn.hzc.fortess.system.eventbus.EventExecute;
import cn.hzc.fortess.system.eventbus.LoginLogEvent;
import cn.hzc.fortess.system.node.MenuNode;
import cn.hzc.fortess.system.service.MenuService;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Api(tags = {"用户登录"})
@Controller
public class LoginController extends BaseController {

    private static final Logger log = LoggerFactory.getLogger(LoginController.class);


    @Autowired
    private MenuService menuService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private JwtTokenService jwtTokenService;
    @Autowired
    private SettingService settingService;

    /**
     * 跳转到主页
     */
    @ApiIgnore
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String index(Model model) {

        final ShiroUser user = ShiroKit.getUserNotNull();
        final Integer indexProjectId = selectIndexProject(user);
        final List<Integer> roleIds = user.getRoleList().parallelStream().map(role -> role.getId()).collect(Collectors.toList());
        final Project project = projectService.getById(indexProjectId);
        //生成jwt-token
        jwtTokenService.generate(super.getHttpServletRequest(), user.getId());

        log.info("{}进入主页---------", user.getAccount());
        model.addAttribute("edit_weakpwd", super.getSession().getAttribute(Const.SESSION_WEAK_PWD_TIPS_KEY));

        return toIndexPage(model, project, menuService.getIndexMenuNodes(project, user.isAdministrator() ? null : roleIds));
    }

    private String toIndexPage(Model model, Project project, List<MenuNode> menus) {
        model.addAttribute("menus", Objects.equals(Const.SAM_PROJECT_ID, project.getId()) ? menus : wrap(menus));
        model.addAttribute("projectName", project.getProjectName());
        getSession().setAttribute(KEY_SESSION_CURRENT_PROJECT_ID, project.getId());

        //


        return "/index.html";
    }

    @ApiIgnore
    @RequestMapping(value = "/index/{projectId}", method = RequestMethod.POST)
    @ResponseBody
    public ResponseData index4Project(@PathVariable(value = "projectId") final Integer projectId) {
        getSession().setAttribute(KEY_SESSION_CURRENT_PROJECT_ID, projectId);
        return ResponseData.success();
    }

    private final List<MenuNode> wrap(List<MenuNode> menuNodes) {
        if (CollectionUtils.isEmpty(menuNodes)
                || CollectionUtils.isEmpty(menuNodes.get(0).getChildren())) {
            return Lists.newArrayList();
        }
        return menuNodes.get(0).getChildren();
    }


    /**
     * 跳转到登录页面
     */
    @ApiIgnore
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login() {
        if (ShiroKit.isAuthenticated() || ShiroKit.getUser() != null) {
            return REDIRECT + "/";
        } else {
            return "/login.html";
        }
    }

    private void checkKaptcha() {
        if (!H5ToolUtil.isOpenCaptchaCode()) {
            return;
        }
        final String serverKaptcha = (String) getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
        final String requestKaptcha = super.getParam(Const.KAPTCHA_SESSION_KEY);
        if (requestKaptcha == null || (!requestKaptcha.equalsIgnoreCase(serverKaptcha))) {
            log.warn("登录验证码校验失败,server:{},request:{}", serverKaptcha, requestKaptcha);
            throw new InvalidKaptchaException();
        }
        getSession().removeAttribute(Constants.KAPTCHA_SESSION_KEY);
    }

    /**
     * 点击登录执行的动作
     */
    @ApiOperation("登录")
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(Model model) {

        String username = super.getParam("username").trim();
        String password = super.getParam("password").trim();
        String remember = super.getParam("remember");

        checkKaptcha();

        UsernamePasswordToken token = new UsernamePasswordToken(username, password.toCharArray(), "on".equals(remember));

        ShiroKit.getSubject().login(token);

        final ShiroUser shiroUser = ShiroKit.getUserNotNull();

        saveLoginInfo(shiroUser);

        saveLoginLog(shiroUser);

        weakPwdCheck(password);

        return REDIRECT + "/";
    }

    private void weakPwdCheck(String pwd) {

        super.getSession().setAttribute(Const.SESSION_WEAK_PWD_TIPS_KEY, ("a123456".equals(pwd)
                || "123456".equals(pwd) || "111111".equals(pwd))
                && "yes".equalsIgnoreCase(settingService.getValByKey("WEAK_PWD_TIPS")) ? 1 : 0);
    }


    private void saveLoginInfo(ShiroUser shiroUser) {

        super.getSession().setAttribute("shiroUser", shiroUser);
        super.getSession().setAttribute("username", shiroUser.getAccount());

        ShiroKit.getSession().setAttribute("sessionFlag", true);

    }

    private void saveLoginLog(ShiroUser shiroUser) {
        EventExecute.me().post(new LoginLogEvent.Builder().ip(HttpContext.getIp())
                .lesseeId(shiroUser.getLesseeId())
                .logDetail(shiroUser.toString())
                .loginName(shiroUser.getAccount())
                .logName("登录")
                .logStatus("SUCCESS").uaAgent(HttpContext.getUaAgent()).build());
    }

    /**
     * 退出登录
     */
    @ApiOperation("退出登录")
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logout() {
        Integer userId = ShiroKit.getUser().getId();
        saveLogoutLog(ShiroKit.getUser());
        ShiroKit.getSubject().logout();
        deleteAllCookie();
        deleteUserApiToken(userId);
        return REDIRECT + "/login";
    }

    private void deleteUserApiToken(Integer userId) {
        jwtTokenService.removeJwtToken(userId);
    }

    private void saveLogoutLog(ShiroUser shiroUser) {
        if (shiroUser == null) {
            return;
        }
        EventExecute.me().post(new LoginLogEvent.Builder().ip(HttpContext.getIp())
                .lesseeId(shiroUser.getLesseeId())
                .logDetail("正常退出登录")
                .loginName(shiroUser.getAccount())
                .logName("注销")
                .logStatus("SUCCESS").uaAgent(HttpContext.getUaAgent()).build());
    }


    private Integer selectIndexProject(ShiroUser user) {

        //默认跳转至本工程的SAM权限后台
        Integer indexProjectId = null;

        //优先级高，多后台跳转指定的项目
        if (getSession().getAttribute(KEY_SESSION_CURRENT_PROJECT_ID) != null) {
            indexProjectId = Integer.parseInt(getSession().getAttribute(KEY_SESSION_CURRENT_PROJECT_ID).toString());
        } else if (user.isAdministrator()) {
            indexProjectId = Const.SAM_PROJECT_ID;
        } else {

            final List<Project> projects = projectService.getProjectByUserRole(user);
            indexProjectId = projects.size() > 0 ? projects.get(0).getId() : null;
        }

        return indexProjectId;
    }

    @Override
    protected String moduleName() {
        return null;
    }
}
